home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / satelite / msat09.tgz / DOWNLOAD.C < prev    next >
Text File  |  1994-09-17  |  20KB  |  863 lines

  1. /*
  2.  *   Copyright 1992, 1993, 1994 John Melton (G0ORX/N6LYT)
  3.  *              All Rights Reserved
  4.  *
  5.  *   This program is free software; you can redistribute it and/or modify
  6.  *   it under the terms of the GNU General Public License as published by
  7.  *   the Free Software Foundation; either version 1, or (at your option)
  8.  *   any later version.
  9.  *
  10.  *   This program is distributed in the hope that it will be useful,
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *   GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program; if not, write to the Free Software
  17.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21. /*
  22.     downloaded.c
  23.  
  24.     List downloaded pacsat files.
  25.  
  26.     John Melton
  27.     G0ORX, N6LYT
  28.  
  29.     4 Charlwoods Close
  30.     Copthorne
  31.     West Sussex
  32.     RH10 3QZ
  33.     England
  34.  
  35.     INTERNET:    g0orx@amsat.org
  36.             n6lyt@amsat.org
  37.             john@images.demon.co.uk
  38.             J.D.Melton@slh0613.icl.wins.co.uk
  39.  
  40.     History:
  41.  
  42.     0.1    Initial version.             G0ORX
  43.     0.2    Added Extract.                G0ORX
  44.     0.3    Added view selection            G0ORX
  45.     0.4    Fixed selected entry after update.    G0ORX
  46.     0.5    Converted to Xaw.            G4KLX
  47.     0.6    Added double click for view.        G4KLX
  48.         Added "Logs" to view menu.
  49.         Added viewlogs.
  50.     0.7    Added Order button.            G4KLX
  51.         Added WOD logs to logs viewing.
  52. */
  53.  
  54. #define VERSION_STRING "(version 0.7 by g0orx/n6lyt/g4klx)"
  55.  
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <unistd.h>
  59. #include <sys/types.h>
  60. #include <sys/wait.h>
  61. #include <sys/stat.h>
  62. #include <fcntl.h>
  63. #include <dirent.h>
  64. #include <signal.h>
  65. #include <ctype.h>
  66. #include <time.h>
  67.  
  68. #include <X11/Intrinsic.h>
  69. #include <X11/StringDefs.h>
  70. #include <X11/Shell.h>
  71. #include <X11/Xaw/Cardinals.h>
  72. #include <X11/Xaw/Form.h>
  73. #include <X11/Xaw/Label.h>
  74. #include <X11/Xaw/List.h>
  75. #include <X11/Xaw/Command.h>
  76. #include <X11/Xaw/MenuButton.h>
  77. #include <X11/Xaw/Viewport.h>
  78.  
  79. #include "xawutils.h"
  80. #include "header.h"
  81. #include "ftl0.h"
  82.  
  83. Display *dpy;
  84. int scrn;
  85.  
  86. XtAppContext app_context;
  87.  
  88. typedef struct
  89. {
  90.     XFontStruct *bold_font, *button_font, *menu_font, *label_font, *list_font;
  91. }
  92. Resources;
  93.  
  94. Resources  resources;
  95.  
  96. Widget toplevel, compwindow, quitbutton, updatebutton, extractbutton,
  97.     replybutton, viewtypebutton, viewtypelabel, orderlabel, orderbutton,
  98.     listlabel, viewport, downloadlist;
  99.  
  100. static XtResource resource_list[] =
  101. {
  102.     {"boldFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  103.         XtOffsetOf(Resources, bold_font), XtRString, XtDefaultFont},
  104.     {"buttonFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  105.         XtOffsetOf(Resources, button_font), XtRString, XtDefaultFont},
  106.     {"menuFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  107.         XtOffsetOf(Resources, menu_font), XtRString, XtDefaultFont},
  108.     {"labelFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  109.         XtOffsetOf(Resources, label_font), XtRString, XtDefaultFont},
  110.     {"listFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  111.         XtOffsetOf(Resources, list_font), XtRString, XtDefaultFont}
  112. };
  113.  
  114. static Arg shell_args[] =
  115. {
  116.     {XtNtitle,        (XtArgVal)NULL}
  117. };
  118.  
  119. static Arg form_args[] =
  120. {
  121.     {XtNdefaultDistance,    (XtArgVal)0}
  122. };
  123.  
  124. static Arg label_args[] =
  125. {
  126.     {XtNfromVert,        (XtArgVal)NULL},
  127.     {XtNfromHoriz,        (XtArgVal)NULL},
  128.     {XtNlabel,        (XtArgVal)NULL},
  129.     {XtNwidth,        (XtArgVal)0},
  130.     {XtNfont,        (XtArgVal)NULL},
  131.     {XtNborderWidth,    (XtArgVal)0},
  132.     {XtNresize,        False},
  133.     {XtNjustify,        XtJustifyLeft},
  134.     {XtNvertDistance,    (XtArgVal)6},
  135.     {XtNhorizDistance,    (XtArgVal)8},
  136.     {XtNtop,        XtChainTop},
  137.     {XtNbottom,        XtChainTop},
  138.     {XtNleft,        XtChainLeft},
  139.     {XtNright,        XtChainLeft}
  140. };
  141.  
  142. static Arg button_args[] =
  143. {
  144.     {XtNcallback,        (XtArgVal)NULL},
  145.     {XtNlabel,        (XtArgVal)NULL},
  146.     {XtNfont,        (XtArgVal)NULL},
  147.     {XtNfromHoriz,        (XtArgVal)NULL},
  148.     {XtNfromVert,        (XtArgVal)NULL},
  149.     {XtNvertDistance,    (XtArgVal)6},
  150.     {XtNhorizDistance,    (XtArgVal)8},
  151.     {XtNresize,        False},
  152.     {XtNtop,        XtChainTop},
  153.     {XtNbottom,        XtChainTop},
  154.     {XtNleft,        XtChainLeft},
  155.     {XtNright,        XtChainLeft}
  156. };
  157.  
  158. static Arg menu_button_args[] =
  159. {
  160.     {XtNlabel,        (XtArgVal)NULL},
  161.     {XtNfont,        (XtArgVal)NULL},
  162.     {XtNfromHoriz,        (XtArgVal)NULL},
  163.     {XtNwidth,        (XtArgVal)80},
  164.     {XtNresize,        False},
  165.     {XtNvertDistance,    (XtArgVal)6},
  166.     {XtNhorizDistance,    (XtArgVal)8},
  167.     {XtNtop,        XtChainTop},
  168.     {XtNbottom,        XtChainTop},
  169.     {XtNleft,        XtChainLeft},
  170.     {XtNright,        XtChainLeft},
  171.     {XtNjustify,        XtJustifyCenter}
  172. };
  173.  
  174. static Arg viewport_args[] =
  175. {
  176.     {XtNfromVert,        (XtArgVal)NULL},
  177.     {XtNwidth,        (XtArgVal)600},
  178.     {XtNheight,        (XtArgVal)150},
  179.     {XtNforceBars,        True},
  180.     {XtNallowVert,        True},
  181.     {XtNresize,        True},
  182.     {XtNvertDistance,    (XtArgVal)0},
  183.     {XtNhorizDistance,    (XtArgVal)0},
  184.     {XtNtop,        XtChainTop},
  185.     {XtNbottom,        XtChainBottom},
  186.     {XtNleft,        XtChainLeft},
  187.     {XtNright,        XtChainRight}
  188. };
  189.  
  190. static Arg list_args[] =
  191. {
  192.     {XtNcallback,        (XtArgVal)NULL},
  193.     {XtNfont,        (XtArgVal)NULL}
  194. };
  195.  
  196. MenuEntry type_menu[] =
  197. {
  198.     {"All",        "type1",    0},
  199.     {"My Mail",    "type2",    1},
  200.     {"Broadcast",    "type3",    2},
  201.     {"Logs",    "type4",    3},
  202.     {"EIS",        "type5",    4}
  203. };
  204.  
  205. MenuEntry order_menu[] =
  206. {
  207.     {"Date/Time",    "order1",    0},
  208.     {"Id",        "order2",    1},
  209.     {"From",    "order3",    2},
  210.     {"To",        "order4",    3},
  211.     {"Size",    "order5",    4},
  212.     {"Title",    "order6",    5}
  213. };
  214.  
  215. #define    MAX_DIR_LIST_SIZE    2000
  216.  
  217. char myCall[16];
  218. char satelliteId[16];
  219.  
  220. int view  = 0;
  221. int order = 0;
  222.  
  223. String dList[MAX_DIR_LIST_SIZE + 1];
  224. int    nList = 0;
  225.  
  226. int lastIndex = 0;
  227.  
  228. void LoadFile(char * fileName);
  229.  
  230. void signal_child(int s)
  231. {
  232.     int pid, pstatus;
  233.  
  234.     signal(SIGCHLD, signal_child);
  235.  
  236.     pid = wait(&pstatus);
  237. }
  238.  
  239. int downloadcomp(const void *first, const void *second)
  240. {
  241.     char **a = (char **)first;
  242.     char **b = (char **)second;
  243.     int n;
  244.  
  245.     switch (order)
  246.     {
  247.         case 0:    /* Date/Time */
  248.             break;
  249.         case 1: /* Id */
  250.             if ((n = strncmp(*b, *a, 8)) != 0)
  251.                 return(n);
  252.             break;
  253.         case 2: /* From */
  254.             if ((n = strncasecmp(*b + 19, *a + 19, 8)) != 0)
  255.                 return(n);
  256.             break;
  257.         case 3: /* To */
  258.             if ((n = strncasecmp(*b + 28, *a + 28, 8)) != 0)
  259.                 return(n);
  260.             break;
  261.         case 4: /* Size */
  262.             if ((n = strncmp(*b + 37, *a + 37, 8)) != 0)
  263.                 return(n);
  264.             break;
  265.         case 5: /* Title */
  266.             if ((n = strncasecmp(*b + 44, *a + 44, 40)) != 0)
  267.                 return(n);
  268.             break;
  269.     }
  270.  
  271.     return(strncmp(*b + 9, *a + 9, 9));
  272. }
  273.  
  274. void Update(void)
  275. {
  276.     DIR        *pDir;
  277.     struct dirent    *pDirent;
  278.     int i;
  279.     Arg args[2];
  280.  
  281.     for (i = 0; i < nList; i++)
  282.         if (dList[i] != NULL)
  283.             XtFree((char *)dList[i]);
  284.  
  285.     nList     = 0;
  286.     lastIndex = -1;
  287.  
  288.     /* walk through the directory of files */
  289.     pDir = opendir(".");
  290.  
  291.     while ((pDirent = readdir(pDir)) != NULL && nList < MAX_DIR_LIST_SIZE)
  292.     {
  293.         /* see if it is a .dl file */
  294.         if (strstr(pDirent->d_name, ".dl") != NULL)
  295.             LoadFile(pDirent->d_name);
  296.     }
  297.  
  298.     closedir(pDir);
  299.  
  300.     dList[nList] = NULL;
  301.  
  302.     qsort(dList, nList, sizeof(String), downloadcomp);
  303.  
  304.     XawListChange(downloadlist, dList, nList, 0, False);
  305.  
  306.     if (nList > 0) XawListHighlight(downloadlist, 0);
  307.  
  308.     XtSetArg(args[0], XtNheight, 0);
  309.     XtSetArg(args[1], XtNwidth,  0);
  310.     XtSetValues(downloadlist, args, TWO);
  311. }
  312.  
  313. void UpdateCb(Widget w, XtPointer client_data, XtPointer call_data)
  314. {
  315.     Update();
  316. }
  317.  
  318. void OrderCb(Widget w, XtPointer client_data, XtPointer call_data)
  319. {
  320.     order = (int)client_data;
  321.  
  322.     XtVaSetValues(orderbutton, XtNlabel, order_menu[order].Label, NULL);
  323.  
  324.     qsort(dList, nList, sizeof(String), downloadcomp);
  325.  
  326.     XawListChange(downloadlist, dList, nList, 0, False);
  327.  
  328.     if (nList > 0) XawListHighlight(downloadlist, 0);
  329. }
  330.  
  331. void ViewTypeCb(Widget w, XtPointer client_data, XtPointer call_data)
  332. {
  333.     view = (int)client_data;
  334.  
  335.     XtVaSetValues(viewtypebutton, XtNlabel, type_menu[view].Label, NULL);
  336.  
  337.     Update();
  338. }
  339.  
  340. void LoadFile(char *fileName)
  341. {
  342.     FILE *hFile;
  343.     int nBytes;
  344.     char *pBuffer, *source, *destination;
  345.     static struct tm *GMT;
  346.     char szTemp[128];
  347.     int headerSize;
  348.     HEADER *pHeader;
  349.     int j;
  350.     char *p;
  351.     int display;
  352.  
  353.     /* open the file */
  354.     if ((hFile = fopen(fileName, "r")) == NULL)
  355.     {
  356.         sprintf(szTemp, "Cannot open file %s", fileName);
  357.         MessageBox(szTemp);
  358.         return;
  359.     }
  360.  
  361.     /* get the header */
  362.     pBuffer = XtMalloc(1024);
  363.  
  364.     /* read in the 1K */
  365.     nBytes = fread(pBuffer, 1, 1024, hFile);
  366.  
  367.     /* close the file */
  368.     fclose(hFile);
  369.  
  370.     /* extracting the header */
  371.     if ((pHeader = ExtractHeader(pBuffer, nBytes, &headerSize)) == NULL)
  372.     {
  373.         MessageBox("Invalid header entry");
  374.         XtFree(pBuffer);
  375.         return;
  376.     }
  377.  
  378.     source      = XtNewString(pHeader->source);
  379.     destination = XtNewString(pHeader->destination);
  380.  
  381.     /* truncate the source and destination */
  382.     j = 0;
  383.     while (isalnum(pHeader->source[j]) != '\0') j++;
  384.     pHeader->source[j] = '\0';
  385.  
  386.     j = 0;
  387.     while (isalnum(pHeader->destination[j]) != '\0') j++;
  388.     pHeader->destination[j] = '\0';
  389.  
  390.     GMT = gmtime(&pHeader->uploadTime);
  391.  
  392.     if (strlen(pHeader->title) == 0)
  393.         sprintf(szTemp, "%8lx %02d%02d/%02d%02d %-8s %-8s %6ld %-40s",
  394.             pHeader->fileId,
  395.             GMT->tm_mon + 1, GMT->tm_mday, GMT->tm_hour, GMT->tm_min,
  396.             pHeader->source,
  397.             pHeader->destination,
  398.             pHeader->fileSize,
  399.             pHeader->fileName);
  400.     else
  401.         sprintf(szTemp, "%8lx %02d%02d/%02d%02d %-8s %-8s %6ld %-40s",
  402.             pHeader->fileId,
  403.             GMT->tm_mon + 1, GMT->tm_mday, GMT->tm_hour, GMT->tm_min,
  404.             pHeader->source,
  405.             pHeader->destination,
  406.             pHeader->fileSize,
  407.             pHeader->title);
  408.  
  409.     for (p = source; *p != '\0';p++)
  410.         if (islower(*p)) *p = toupper(*p);
  411.  
  412.     for (p = destination; *p != '\0'; p++)
  413.         if (islower(*p)) *p = toupper(*p);
  414.  
  415.     display = FALSE;
  416.  
  417.     switch (view)
  418.     {
  419.         case 0:
  420.             display = TRUE;
  421.             break;
  422.         case 1:
  423.             if (strstr(source, myCall)      != NULL || 
  424.                 strstr(destination, myCall) != NULL)
  425.                 display = TRUE;
  426.             break;
  427.         case 2:
  428.             if (strstr(destination, "ALL") != NULL)
  429.                 display = TRUE;
  430.             break;
  431.         case 3:
  432.             if (pHeader->fileType >= 100 &&
  433.                 pHeader->fileType != 221)
  434.                 display = TRUE;
  435.             break;
  436.         case 4:
  437.             if (pHeader->fileType == 220 ||
  438.                 pHeader->fileType == 221)
  439.                     display = TRUE;
  440.             break;
  441.         default:
  442.             break;
  443.     }
  444.  
  445.     if (display)
  446.     {
  447.         dList[nList] = XtNewString(szTemp);
  448.         nList++;
  449.     }
  450.         
  451.     XtFree((char *)pHeader);
  452.     XtFree(source);
  453.     XtFree(destination);    
  454.     XtFree(pBuffer);
  455. }
  456.  
  457. void ExtractCb(Widget w, XtPointer client_data, XtPointer call_data)
  458. {
  459.     XawListReturnStruct *selected;
  460.     unsigned long FileId;
  461.     char fileName[128];
  462.     FILE *hFile, *hOut;
  463.     char *pBuffer;
  464.     int headerSize;
  465.     HEADER *pHeader;
  466.     char tmp[128];
  467.     int i, nBytes;
  468.  
  469.     selected = XawListShowCurrent(downloadlist);
  470.  
  471.     if (selected->list_index == XAW_LIST_NONE)
  472.         return;
  473.  
  474.     sscanf(selected->string, "%lx", &FileId);
  475.     sprintf(fileName, "%lx.dl", FileId);
  476.  
  477.     if ((hFile = fopen(fileName, "r")) == NULL)
  478.     {
  479.         MessageBox("Open failed");
  480.         return;
  481.     }
  482.  
  483.     pBuffer = XtMalloc(1024);
  484.  
  485.     nBytes = fread(pBuffer, 1, 1024, hFile);
  486.  
  487.     if ((pHeader = ExtractHeader(pBuffer, nBytes, &headerSize)) == NULL)
  488.     {
  489.         MessageBox("Bad header");
  490.         XtFree(pBuffer);
  491.         fclose(hFile);
  492.         return;
  493.     }
  494.  
  495.     mkdir("msgs", 0755);
  496.  
  497.     i = strlen(pHeader->userFileName) - 1;
  498.  
  499.     while (i > 0)
  500.     {
  501.         if (pHeader->userFileName[i] == '\\')
  502.         {
  503.             i++;
  504.             break;
  505.         }
  506.             
  507.         i--;
  508.     }
  509.  
  510.     if (i < 0)
  511.         if (strcmp(pHeader->fileExt, "   ") != 0)
  512.             sprintf(fileName, "msgs/%s.%s", pHeader->fileName, pHeader->fileExt);
  513.         else
  514.             sprintf(fileName, "msgs/%s", pHeader->fileName);
  515.     else
  516.         sprintf(fileName, "msgs/%s", pHeader->userFileName + i);
  517.  
  518.     if ((hOut = fopen(fileName, "w")) == NULL)
  519.     {
  520.         sprintf(tmp, "Cannot create %s", fileName);
  521.         MessageBox(tmp);
  522.         XtFree((char *)pHeader);
  523.         XtFree(pBuffer);
  524.         fclose(hFile);
  525.         return;
  526.     }
  527.  
  528.     fseek(hFile, pHeader->bodyOffset, SEEK_SET);
  529.  
  530.     while ((nBytes = fread(pBuffer, 1, 1024, hFile)) > 0)
  531.         fwrite(pBuffer, 1, nBytes, hOut);
  532.  
  533.     fclose(hFile);
  534.     fclose(hOut);
  535.  
  536.     sprintf(tmp, "Message extracted to file %s", fileName);
  537.     MessageBox(tmp);
  538.  
  539.     XtFree((char *)pHeader);
  540.     XtFree(pBuffer);
  541. }
  542.  
  543. void ViewText(char *fileName)
  544. {
  545.     int pid;
  546.     
  547.     if ((pid = fork()) == 0)
  548.     {
  549.         /* the child process */
  550.         execlp("viewtext", "viewtext", fileName, NULL);
  551.     }
  552.     else if (pid > 0)
  553.     {
  554.         /* success */
  555.     }
  556.     else
  557.     {
  558.         MessageBox("Cannot fork viewer");
  559.     }
  560. }
  561.  
  562. void ViewImage(char *fileName)
  563. {
  564.     int pid;
  565.     
  566.     if ((pid = fork()) == 0)
  567.     {
  568.         /* the child process */
  569.         execlp("phs", "phs", fileName, "xloadimage", "-quiet", NULL);
  570.     }
  571.     else if (pid > 0)
  572.     {
  573.         /* success */
  574.     }
  575.     else
  576.     {
  577.         MessageBox("Cannot fork viewer");
  578.     }
  579. }
  580.  
  581. void ViewLog(char *fileName, char *title)
  582. {
  583.     int pid;
  584.     
  585.     if ((pid = fork()) == 0)
  586.     {
  587.         /* the child process */
  588.         execlp("phs", "phs", fileName, "viewlog", title, NULL);
  589.     }
  590.     else if (pid > 0)
  591.     {
  592.         /* success */
  593.     }
  594.     else
  595.     {
  596.         MessageBox("Cannot fork viewer");
  597.     }
  598. }
  599.  
  600. void SelectCb(Widget w, XtPointer client_data, XtPointer call_data)
  601. {
  602.     XawListReturnStruct *selected;
  603.     unsigned long FileId;
  604.     char fileName[128];
  605.     FILE *hFile;
  606.     int nBytes;
  607.     char * pBuffer;
  608.     int headerSize;
  609.     HEADER *pHeader;
  610.     char szCommand[128];
  611.  
  612.     selected = (XawListReturnStruct *)call_data;
  613.  
  614.     if (selected->list_index != lastIndex)
  615.     {
  616.         lastIndex = selected->list_index;
  617.         return;
  618.     }
  619.  
  620.     lastIndex = -1;
  621.  
  622.     sscanf(selected->string, "%lx", &FileId);
  623.  
  624.     /* open the file */
  625.     sprintf(fileName, "%lx.dl", FileId);
  626.  
  627.     if ((hFile = fopen(fileName, "r")) == NULL)
  628.     {
  629.         sprintf(szCommand, "Cannot open file %s", fileName);
  630.         MessageBox(szCommand);
  631.         return;
  632.     }
  633.  
  634.     pBuffer = XtMalloc(1024);
  635.  
  636.     /* read in the header */
  637.     nBytes = fread(pBuffer, 1, 1024, hFile);
  638.  
  639.     /* close the file */
  640.     fclose(hFile);
  641.  
  642.     /* extracting the header */
  643.     pHeader = ExtractHeader(pBuffer, nBytes, &headerSize);
  644.  
  645.     XtFree(pBuffer);
  646.  
  647.     strcpy(szCommand, "");
  648.  
  649.     switch (pHeader->fileType)
  650.     {
  651.     case 0:
  652.     case 1:
  653.     case 2:
  654.     case 8:
  655.     case 9:
  656.     case 12:
  657.     case 13:
  658.         switch (pHeader->compression)
  659.         {
  660.         case 0:
  661.         case 2:
  662.         case 3:
  663.             ViewText(fileName);
  664.             break;
  665.         case 1:
  666.             MessageBox("Sorry don't know how to do PKARC");
  667.             break;
  668.         default:
  669.             MessageBox("Sorry do not know how to uncompress.");
  670.             break;
  671.         }
  672.         break;
  673.     case 14:
  674.     case 15:
  675.     case 16:
  676.     case 221:
  677.         ViewImage(fileName);
  678.         break;
  679.     case 201:
  680.     case 202:
  681.     case 203:
  682.     case 208:
  683.     case 217:
  684.         ViewLog(fileName, pHeader->fileName);
  685.         break;
  686.     default:
  687.         MessageBox("Do not know how to view message");
  688.         break;
  689.     }
  690.  
  691.     XtFree((char *)pHeader);
  692. }
  693.  
  694. void ReplyCb(Widget w, XtPointer client_data, XtPointer call_data)
  695. {
  696.     XawListReturnStruct *selected;
  697.     unsigned long FileId;
  698.     char fileName[128];
  699.     int pid;
  700.  
  701.     selected = XawListShowCurrent(downloadlist);
  702.  
  703.     if (selected->list_index == XAW_LIST_NONE)
  704.         return;
  705.  
  706.     sscanf(selected->string, "%lx", &FileId);
  707.  
  708.     /* open the file */
  709.     sprintf(fileName, "%lx.dl", FileId);
  710.     
  711.     if ((pid=fork()) == 0)
  712.     {
  713.         /* the child process */
  714.         execlp("message", "message", fileName, NULL);
  715.     }
  716.     else if (pid > 0)
  717.     {
  718.         /* success */
  719.     }
  720.     else
  721.     {
  722.         MessageBox("Cannot fork message");
  723.     }
  724. }
  725.  
  726. void QuitCb(Widget w, XtPointer client_data, XtPointer call_data)
  727. {
  728.     XtDestroyApplicationContext(app_context);
  729.  
  730.     exit(0);
  731. }
  732.  
  733. int main(int argc, char **argv)
  734. {
  735.     static XtCallbackRec callback[2];
  736.     char title[80], *s;
  737.  
  738.     signal(SIGCHLD, signal_child);
  739.  
  740.     if ((s = getenv("MYCALL")) == NULL)
  741.         strcpy(myCall, "NOCALL");
  742.     else
  743.         strcpy(myCall, s);
  744.  
  745.     if ((s = getenv("SATELLITE")) == NULL)
  746.     {
  747.         printf("SATELLITE environment variable not set.\n");
  748.         return(1);
  749.     }
  750.  
  751.     strcpy(satelliteId , s);
  752.  
  753.     toplevel = XtAppInitialize(&app_context, "Xpb", NULL, 0, &argc, argv,
  754.                 NULL, shell_args, XtNumber(shell_args));
  755.  
  756.     sprintf( title, "downloaded:%s %s", satelliteId, VERSION_STRING );
  757.     XtVaSetValues(toplevel, XtNtitle, title, NULL);
  758.  
  759.     dpy  = XtDisplay(toplevel);
  760.     scrn = DefaultScreen(dpy);
  761.  
  762.     XtGetApplicationResources(toplevel, &resources,
  763.                 resource_list, XtNumber(resource_list),
  764.                 NULL, ZERO);
  765.  
  766.     compwindow = XtCreateManagedWidget("appForm", formWidgetClass,
  767.                 toplevel, form_args, XtNumber(form_args));
  768.  
  769.     callback[0].callback = QuitCb;
  770.     callback[0].closure  = toplevel;
  771.     button_args[0].value = (XtArgVal)callback;
  772.     button_args[1].value = (XtArgVal)"Quit";
  773.     button_args[2].value = (XtArgVal)resources.button_font;
  774.     quitbutton = XtCreateManagedWidget("quitButton", commandWidgetClass,
  775.                 compwindow, button_args, XtNumber(button_args));
  776.  
  777.     callback[0].callback = UpdateCb;
  778.     callback[0].closure  = toplevel;
  779.     button_args[0].value = (XtArgVal)callback;
  780.     button_args[1].value = (XtArgVal)"Update";
  781.     button_args[3].value = (XtArgVal)quitbutton;
  782.     updatebutton = XtCreateManagedWidget("updateButton", commandWidgetClass,
  783.                 compwindow, button_args, XtNumber(button_args));
  784.  
  785.     callback[0].callback = ExtractCb;
  786.     callback[0].closure  = toplevel;
  787.     button_args[0].value = (XtArgVal)callback;
  788.     button_args[1].value = (XtArgVal)"Extract";
  789.     button_args[3].value = (XtArgVal)updatebutton;
  790.     extractbutton = XtCreateManagedWidget("extractButton", commandWidgetClass,
  791.                 compwindow, button_args, XtNumber(button_args));
  792.  
  793.     callback[0].callback = ReplyCb;
  794.     callback[0].closure  = toplevel;
  795.     button_args[0].value = (XtArgVal)callback;
  796.     button_args[1].value = (XtArgVal)"Reply";
  797.     button_args[3].value = (XtArgVal)extractbutton;
  798.     replybutton = XtCreateManagedWidget("replyButton", commandWidgetClass,
  799.                 compwindow, button_args, XtNumber(button_args));
  800.  
  801.     label_args[0].value = (XtArgVal)NULL;
  802.     label_args[1].value = (XtArgVal)replybutton;
  803.     label_args[2].value = (XtArgVal)"View";
  804.     label_args[4].value = (XtArgVal)resources.label_font;
  805.     viewtypelabel = XtCreateManagedWidget("viewtypeLabel", labelWidgetClass,
  806.                 compwindow, label_args, XtNumber(label_args));
  807.  
  808.     menu_button_args[0].value = (XtArgVal)type_menu[0].Label;
  809.     menu_button_args[1].value = (XtArgVal)resources.button_font;
  810.     menu_button_args[2].value = (XtArgVal)viewtypelabel;
  811.     viewtypebutton = XtCreateManagedWidget("viewtypeButton", menuButtonWidgetClass,
  812.                 compwindow, menu_button_args, XtNumber(menu_button_args));
  813.  
  814.     createMenuPopup(viewtypebutton, resources.menu_font, type_menu,
  815.             XtNumber(type_menu), ViewTypeCb);
  816.  
  817.     label_args[0].value = (XtArgVal)NULL;
  818.     label_args[1].value = (XtArgVal)viewtypebutton;
  819.     label_args[2].value = (XtArgVal)"Order";
  820.     label_args[4].value = (XtArgVal)resources.label_font;
  821.     orderlabel = XtCreateManagedWidget("orderLabel", labelWidgetClass,
  822.                 compwindow, label_args, XtNumber(label_args));
  823.  
  824.     menu_button_args[0].value = (XtArgVal)order_menu[0].Label;
  825.     menu_button_args[1].value = (XtArgVal)resources.button_font;
  826.     menu_button_args[2].value = (XtArgVal)orderlabel;
  827.     orderbutton = XtCreateManagedWidget("orderButton", menuButtonWidgetClass,
  828.                 compwindow, menu_button_args, XtNumber(menu_button_args));
  829.  
  830.     createMenuPopup(orderbutton, resources.menu_font, order_menu,
  831.             XtNumber(order_menu), OrderCb);
  832.  
  833.     label_args[0].value = (XtArgVal)quitbutton;
  834.     label_args[1].value = (XtArgVal)NULL;
  835.     label_args[2].value = (XtArgVal)"       Id Date/Time From     To         Size Title";
  836.     label_args[3].value = (XtArgVal)500;
  837.     label_args[4].value = (XtArgVal)resources.list_font;
  838.     listlabel = XtCreateManagedWidget("listLabel", labelWidgetClass,
  839.                 compwindow, label_args, XtNumber(label_args));
  840.  
  841.     viewport_args[0].value = (XtArgVal)listlabel;
  842.     viewport = XtCreateManagedWidget("downloadedViewport", viewportWidgetClass,
  843.                 compwindow, viewport_args, XtNumber(viewport_args));
  844.         
  845.     callback[0].callback = SelectCb;
  846.     callback[0].closure  = toplevel;
  847.     list_args[0].value = (XtArgVal)callback;
  848.     list_args[1].value = (XtArgVal)resources.list_font;
  849.     downloadlist = XtCreateManagedWidget("downloadedList", listWidgetClass,
  850.                 viewport, list_args, XtNumber(list_args));
  851.  
  852.     createMessagePopup(resources.bold_font, resources.button_font);
  853.  
  854.     view = 0;
  855.     Update();
  856.  
  857.     XtRealizeWidget(toplevel);
  858.  
  859.     XtAppMainLoop(app_context);
  860.  
  861.     return(0);
  862. }
  863.